﻿using ExcellentProjectPlus.Dominio.Calificaciones.Entidades;
using ExcellentProjectPlus.Dominio.Calificaciones.Repositorios;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExcellentProjectPlus.Dominio.Calificaciones.Servicios.Periodos
{
    public class ServicioDeAdministracionDePeriodos : IServicioDeAdministracionDePeriodos
    {
        #region Atributos
        IUnidadDeTrabajoCalificaciones _unidadDeTrabajo;
        #endregion


        #region Constructores
        public ServicioDeAdministracionDePeriodos(IUnidadDeTrabajoCalificaciones unidadDeTrabajo)
        {
            _unidadDeTrabajo = unidadDeTrabajo;
        }
        #endregion

        public IEnumerable<Periodo> ObtenerPeriodos()
        {
            return _unidadDeTrabajo.RepositorioPeriodos.Obtener();
        }

        public Periodo ObtenerPeriodoPorId(int id)
        {
            return _unidadDeTrabajo.RepositorioPeriodos.ObtenerPorId(id);
        }

        public Periodo ObtenerPeriodoPorIdConParciales(int id)
        {
            var periodo = _unidadDeTrabajo.RepositorioPeriodos.Obtener(p => p.Id == id, null, "Parciales");
            if (periodo.Count() > 0)
                return periodo.ToList()[0];
            return null;
        }

        public void AgregarPeriodo(Periodo periodo)
        {
            _unidadDeTrabajo.RepositorioPeriodos.Agregar(periodo);
            _unidadDeTrabajo.Confirmar();
        }

        public void ModificarPeriodo(Periodo periodo)
        {
            var listaDeParciales = _unidadDeTrabajo.RepositorioParciales
                .Obtener(p => p.IdPeriodo == periodo.Id).ToList();

            if (listaDeParciales.Any(p => periodo.FechaInicio > p.FechaInicio))
                throw new ArgumentOutOfRangeException("No se puede actualizar el periodo debido a que existe conflictos con la fecha de incio de uno o más parciales", 
                    (Exception)null);

            if (listaDeParciales.OrderByDescending(p => p.FechaFin).FirstOrDefault().FechaFin > periodo.FechaFin)
                throw new ArgumentOutOfRangeException("No se puede actualizar el periodo debido a que existe conflictos con la fecha de fin de uno o más parciales",
                    (Exception)null);

            _unidadDeTrabajo.RepositorioPeriodos.Modificar(periodo);
            _unidadDeTrabajo.Confirmar();
        }

        public void EliminarPeriodo(Periodo periodo)
        {
            //Solo se podra eliminar periodos si no existen calificaciones asignadas
            if (periodo.Cursos.Count > 0)
                throw new InvalidOperationException("No se puede eliminar el periodo, debido a que tiene asociado cursos");
            var parciales = periodo.Parciales.ToList();
            foreach (var parcial in parciales)
            {
                _unidadDeTrabajo.RepositorioParciales.Eliminar(parcial);
            }

            _unidadDeTrabajo.RepositorioPeriodos.Eliminar(periodo);
            _unidadDeTrabajo.Confirmar();
        }

        public IEnumerable<Periodo> ObtenerPeriodosPaginado(int pagina, int tamanio)
        {
            return _unidadDeTrabajo.RepositorioPeriodos.Obtener(orderBy: c => c.OrderBy(cal => cal.Id),
                page: pagina, pageSize: tamanio);
        }

        public List<Periodo> ObtenerPeriodosVigentes()
        {
            var periodos = _unidadDeTrabajo.RepositorioPeriodos.ObtenerConsulta(p => p.FechaFin > DateTime.Now).ToList();
            return periodos;
        }
    }
}
